/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/

/****************************************************************************
* FILENAME
*   NUC900_ADC.c
*
* VERSION
*   1.0
*
* DESCRIPTION
*   The ADC device library of Nuvoton MCU
*
* DATA STRUCTURES
*   ADC_HANDLE    for ADC settings
*
* FUNCTIONS
*   adcInit   
*   adcOpen
*   adcClose
*   adcRead
*   adcIoctl
*   adcChangeTscMode
*   adcChangeChannel
*
* HISTORY
*   2007-11-23    Ver 1.0 Create
*
* REMARK
*   None
****************************************************************************/
#ifdef ECOS
#include "stdio.h"
#include "drv_api.h"
#include "diag.h"
#include "wbtypes.h"
#include "wbio.h"
#else
#include "wblib.h"
#endif
#include "nuc900_ADC.h"
#include "nuc900_reg.h"

#ifdef ECOS
#define	Successful  	0
#define	Fail        	1
#define sysprintf		diag_printf
#define sysPrintf		diag_printf
#define sysGetTicks(TIMER0)  cyg_current_time()
#endif

#ifdef ECOS
#define IRQ_ADC   			31
cyg_interrupt  adc_interrupt;
cyg_handle_t   adc_irq_handle;
#endif

#ifdef ECOS
static cyg_uint32 adcISR(cyg_vector_t vector, cyg_addrword_t data);
#else
VOID adcISR(VOID);
#endif

#define ADC_FIFO_LENGTH 128
#define NULL 0

typedef struct 
{
    ADC_TSC_MODE mode;
    ADC_CALLBACK adc_callback;
    ADC_CALLBACK wt_callback;
    ADC_CALLBACK lv_callback;
    UINT32 adc_userData;
    UINT32 wt_userData;
    UINT32 lv_userData;
    
    INT16 fifoX[ADC_FIFO_LENGTH];
    INT32 fifoHeadX;
    INT32 fifoTailX;
    INT32 fifoLengthX;

    INT16 fifoY[ADC_FIFO_LENGTH];
    INT32 fifoHeadY;
    INT32 fifoTailY;
    INT32 fifoLengthY;

} ADC_HANDLE;

static ADC_HANDLE adcHandler;



/****************************************************************************
* FUNCTION
*   adcInit
*
* DESCRIPTION
*   The init function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   None
*
* OUTPUTS
*   Successful
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
INT adcInit(VOID)
{
    UINT32 tmp32;
	
	/* enable the ADC clock */
	tmp32 = readw(REG_CLKEN);
	tmp32 = tmp32 | 0x10000000;
  	writew(REG_CLKEN,tmp32);

    //set interrupt */ 
#ifdef ECOS
	outpw(REG_AIC_SCR31, 0xC1);
	cyg_drv_interrupt_create(IRQ_ADC, 8, 0, adcISR, 0,
							&adc_irq_handle, &adc_interrupt);
    cyg_drv_interrupt_attach(adc_irq_handle);
    cyg_drv_interrupt_unmask(IRQ_ADC);
#else  
	sysSetInterruptType(IRQ_ADC, HIGH_LEVEL_SENSITIVE);
	sysInstallISR(IRQ_LEVEL_1, IRQ_ADC, (PVOID)adcISR);
	sysSetLocalInterrupt(ENABLE_IRQ);                            /* enable CPSR I bit */
	sysEnableInterrupt(IRQ_ADC);  
#endif
    return Successful;
}


/****************************************************************************
* FUNCTION
*   adcOpen
*
* DESCRIPTION
*   The open function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   mode           ADC touch screen conversion mode
*   clockDiv       ADC input clock divider
*   channel        Select ADC input for normal mode
*
* OUTPUTS
*   Successful
*   ADC_ERR_ARGS   Wrong argument(s)
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/

INT adcOpen(ADC_TSC_MODE mode, INT32 clockDiv, ADC_CHAN channel)
{
    UINT32 reg;
    
    /* Check input parameters. clock divider 0 is not allowed. total clock divider is 7 bits */
    if(clockDiv <= 0 || clockDiv >= 256)
    {
        return ADC_ERR_ARGS;
    }
    
    if((channel & 0x07) != channel)
    {
        return ADC_ERR_ARGS;
    }
    
    /* reset the ADC */
    writew(REG_ADC_CON, ADC_RST);
    writew(REG_ADC_CON, 0x0);
    
    
    adcHandler.mode = mode;
    /* enable ADC and ADC_INT and set control reg */
    if (mode == NORMAL)
    {
       reg = ((clockDiv & 0xFF) << 1) + ((INT32)channel << 9) + (mode << 14);
    }
    else
    {
       reg = ((clockDiv & 0xFF) << 1) + (mode << 14);   
    }
    
    /* Init the FIFO buffer */
    adcHandler.fifoHeadX = 0;
    adcHandler.fifoTailX = 0;
    adcHandler.fifoLengthX = 0;
    adcHandler.fifoHeadY = 0;
    adcHandler.fifoTailY = 0;
    adcHandler.fifoLengthY = 0;

    /* Install the handler and assign arguments */
    adcHandler.adc_callback = NULL;
    adcHandler.adc_userData = 0;
    
    reg = reg | ADC_EN;
    writew(REG_ADC_CON, reg);
     
    return Successful;
}


/****************************************************************************
* FUNCTION
*   adcClose
*
* DESCRIPTION
*   The close function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   None
*
* OUTPUTS
*   Scccessful
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
INT adcClose(VOID)
{
    /* disable ADC and ADC_INT */
    writew(REG_ADC_CON, ADC_RST);
    writew(REG_ADC_CON, 0x00000000);       
    return Successful;
}


/****************************************************************************
* FUNCTION
*   adcRead
*
* DESCRIPTION
*   The read function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   bufX                Data buffer for x-position data
*   bufY                Data buffer for y-position data
*   datacnt             The length of ADC x- and y-position data from FIFO
*
* OUTPUTS
*   i                   data count actually
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/

INT adcRead(INT16 *bufX, INT16 *bufY, INT32 dataCnt)
{
    //UINT32 reg;
    INT32 i;
    INT16 *fifoX, *fifoY;
    INT32 headX, headY;
    INT32 fifoLengthX, readLengthX;
    INT32 fifoLengthY, readLengthY;
        //INT32 readCnt;
   
    fifoX = adcHandler.fifoX;
    fifoY = adcHandler.fifoY;
    headX = adcHandler.fifoHeadX;
    headY = adcHandler.fifoHeadY;
    fifoLengthX = adcHandler.fifoLengthX;
    fifoLengthY = adcHandler.fifoLengthY;    
   
    readLengthX = 0;
    readLengthY = 0;
    
    for (i = 0; i < dataCnt; i++)
    {
        if (fifoLengthX > readLengthX)
        {
           bufX[i] = fifoX[headX];
           readLengthX++;
           headX++;
           if (headX >= ADC_FIFO_LENGTH)
           {
              headX = 0;
           }
        }
        else
        {
           /* FIFO is empty, just return */
           break;
        }
    }
    
    for (i = 0; i < dataCnt; i++)
    {
        if (fifoLengthY > readLengthY)
        {
           bufY[i] = fifoY[headY];
           readLengthY++;
           headY++;
           if (headY >= ADC_FIFO_LENGTH)
           {
              headY = 0;
           }
        }
        else
        {
           /* FIFO is empty, just return */
           break;
        }     
    }
      
           
    /* Update FIFO information */
    adcHandler.fifoHeadX = headX;
    adcHandler.fifoLengthX -= readLengthX;
    adcHandler.fifoHeadY = headY;
    adcHandler.fifoLengthY -= readLengthY;    
    
    return i;
}
/****************************************************************************
* FUNCTION
*   adcIoctl
*
* DESCRIPTION
*   The ioctl function of PWM device library
*
* CALLED BY
*   various components
*
* INPUTS
*   cmd          The command of adcIoctl function
*   arg1         The first argument of adcIoctl function
*   arg2         The second argument of adcIoctl function
*
* OUTPUTS
*   Successful
*   ADC_ERR_CMD       Wrong command of adcIoctl
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
INT adcIoctl(ADC_CMD cmd, INT32 arg1, INT32 arg2)
{
    switch(cmd)
    {
       case START_CONV:
       {
          UINT32 reg;
          reg = inpw(REG_ADC_CON);
          reg = reg | ADC_CONV;
          outpw(REG_ADC_CON, reg);
          break;
       }
       
       case WT_INT_ON:
       {
          UINT32 reg;
          ADC_CALLBACK wt_callback;
            
          reg = inpw(REG_ADC_CON);
          reg = reg | ADC_WT_INT_EN;
            
          wt_callback = (ADC_CALLBACK) arg1;
          if (wt_callback != NULL )
          {
             adcHandler.wt_callback = wt_callback;
             adcHandler.wt_userData = (UINT32)arg2;
          }

          outpw(REG_ADC_CON, reg);  
          break;
       } 

       case WT_INT_OFF:
       {
          UINT32 reg;
            
          reg = inpw(REG_ADC_CON);  
          reg = reg & (~ADC_WT_INT_EN);
            
          adcHandler.wt_callback = NULL;
          adcHandler.wt_userData = NULL;
          outpw(REG_ADC_CON, reg);                        
          break;
       }
           
       case LV_INT_ON:
       {
          UINT32 reg;
          ADC_CALLBACK lv_callback;
            
          reg = inpw(REG_ADC_CON);
          reg = reg | ADC_LV_INT_EN;
            
          lv_callback = (ADC_CALLBACK) arg1;
          if (lv_callback != NULL )
          {
             adcHandler.lv_callback = lv_callback;
             adcHandler.lv_userData = (UINT32)arg2;
          }

          outpw(REG_ADC_CON, reg);                        
          break;
       } 
       
       case LV_INT_OFF:
       {
          UINT32 reg;
            
          reg = inpw(REG_ADC_CON);  
          reg = reg & (~ADC_LV_INT_EN);
            
          adcHandler.lv_callback = NULL;
          adcHandler.lv_userData = NULL;
          outpw(REG_ADC_CON, reg);                        
          break;       
       }
       
       case ADC_INT_ON:
       {
          UINT32 reg;
          ADC_CALLBACK adc_callback;
            
          reg = inpw(REG_ADC_CON);
          reg = reg | ADC_INT_EN;
            
          adc_callback = (ADC_CALLBACK) arg1;
          if (adc_callback != NULL )
          {
             adcHandler.adc_callback = adc_callback;
             adcHandler.adc_userData = (UINT32)arg2;
          }

          outpw(REG_ADC_CON, reg);                        
            
          /* Flush the FIFO */
          adcHandler.fifoHeadX = 0;
          adcHandler.fifoTailX = 0;
          adcHandler.fifoLengthX = 0;
          adcHandler.fifoHeadY = 0;
          adcHandler.fifoTailY = 0;
          adcHandler.fifoLengthY = 0;          
     
          break;
       }   
    
       case ADC_INT_OFF:
       {
          UINT32 reg;
            
          reg = inpw(REG_ADC_CON);  
          reg = reg & (~ADC_INT_EN);
            
          adcHandler.adc_callback = NULL;
          adcHandler.adc_userData = NULL;
          outpw(REG_ADC_CON, reg);                        
          break;       
       }
       
       case ADC_TSC_XY_CTL:
       {
          UINT32 reg;
          reg = inpw(REG_ADC_TSC);
          
          if (arg1 == 0)
          {
             reg = reg & (~ADC_TSC_XY);
          }
          else
          {
             reg = reg | ADC_TSC_XY;
          }
          outpw(REG_ADC_TSC, reg);
          break;
       }
       
       case ADC_PU_ON:
       {
          UINT32 reg;
            
          reg = inpw(REG_ADC_TSC);
          if (arg1 == 0)
          {
              reg = reg & (~ADC_PU_EN);
          }
          else
          {
              reg = reg | ADC_PU_EN;
          }
          outpw(REG_ADC_TSC, reg);          
          break;
       }    
    
       case TSC_TYPE_SW:
       {
          UINT32 reg;
            
          if (arg1 < 0 || arg1 > 3)
          {
             return ADC_ERR_ARGS;
          }
          reg = inpw(REG_ADC_TSC);
          reg = (reg & (~0x00000006)) | (arg1 << 1);
          outpw(REG_ADC_TSC, reg);             
          
          break;
       }    
    
       case ADC_DELAY:
       {
          UINT32 reg;
            
          if (arg1 < 0 || arg1 > 0x3FFFF)
          {
             return ADC_ERR_ARGS;
          }
          reg = inpw(REG_ADC_DLY);
          reg = (reg & (~0x0003FFFF)) | arg1;
          outpw(REG_ADC_DLY, reg);             
          
          break;
       }    

       case WT_DELAY:
       {
          UINT32 reg;
            
          if (arg1 < 0 || arg1 > 0x3FFF)
          {
             return ADC_ERR_ARGS;
          }
          reg = inpw(REG_ADC_DLY);
          reg = (reg & 0x3FFF) | (arg1 << 18);
          outpw(REG_ADC_DLY, reg);             
                   
          break;
       }
       
       case LV_ON:
       {
          UINT32 reg;
            
          reg = inpw(REG_ADC_LV_CON);
          if (arg1 == 0)
          {
              reg = reg & (~ADC_LV_EN);
          }
          else
          {
              reg = reg | ADC_LV_EN;
          }
          outpw(REG_ADC_LV_CON, reg);          
          break;
       }
       
       case LV_SW:
       {
          UINT32 reg;
            
          if (arg1 < 0 || arg1 > 4)
          {
             return ADC_ERR_ARGS;
          }
          reg = inpw(REG_ADC_LV_CON);
          reg = (reg & (~0x00000003)) | arg1;
          outpw(REG_ADC_LV_CON, reg);  
          break;
       }
              
       default:
          return ADC_ERR_CMD;
    }
    
    return Successful;
}

/****************************************************************************
* FUNCTION
*   adcISR
*
* DESCRIPTION
*   The interrupt service routines of ADC
*
* CALLED BY
*   sysIrqHandler
*
* INPUTS
*   None
*
* OUTPUTS
*   None
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
#ifdef ECOS
static cyg_uint32 adcISR(cyg_vector_t vector, cyg_addrword_t data)
{
    UINT32 reg, temp;
    INT16 valueX, valueY;
    INT32 headX, tailX, lengthX;
    INT32 headY, tailY, lengthY;
    INT16 *fifoX, *fifoY;
    ADC_TSC_MODE mode;
    //INT32 i;

    headX   = adcHandler.fifoHeadX;
    tailX   = adcHandler.fifoTailX;
    lengthX = adcHandler.fifoLengthX;
    headY   = adcHandler.fifoHeadY;
    tailY   = adcHandler.fifoTailY;
    lengthY = adcHandler.fifoLengthY;    
    
    fifoX   = adcHandler.fifoX;
    fifoY   = adcHandler.fifoY;
    mode    = adcHandler.mode;
    
    cyg_drv_interrupt_acknowledge(IRQ_ADC);
    reg = readw(REG_ADC_CON);
    
    
    if ((reg & ADC_INT) == ADC_INT)
    {
       if ( (lengthX<ADC_FIFO_LENGTH) && (lengthY<ADC_FIFO_LENGTH))
       {
          if (mode == NORMAL)
          {
             valueX = readw(REG_ADC_XDATA);
                    
             fifoX[tailX] = valueX;
             lengthX++;

    	     tailX++;
             if (tailX == ADC_FIFO_LENGTH)
             {
                tailX = 0;
             }  
          }
 
          if (mode == SEMIAUTO)
          {
             temp = readw(REG_ADC_TSC);
             
             if ((temp & ADC_TSC_XY) == 0)
             {
                valueX = readw(REG_ADC_XDATA);
                    
                fifoX[tailX] = valueX;
                lengthX++;

    	        tailX++;
                if (tailX == ADC_FIFO_LENGTH)
                {
                   tailX = 0;
                }             
             }
             else
             {
                valueY = readw(REG_ADC_YDATA);
                    
                fifoY[tailY] = valueY;
                lengthY++;
    	        tailY++;
                if (tailY == ADC_FIFO_LENGTH)
                {
                   tailY = 0;
                }             
             }    
          } 
          
          if (mode == AUTO)
          {
             valueX = readw(REG_ADC_XDATA);
             valueY = readw(REG_ADC_YDATA);       
             fifoX[tailX] = valueX;
             fifoY[tailY] = valueY;
             lengthX++;
             lengthY++;
    	     tailX++;
    	     tailY++;
             if (tailX == ADC_FIFO_LENGTH)
             {
                tailX = 0;
             }           
             if (tailY == ADC_FIFO_LENGTH)
             {
                tailY = 0;
             }            
          }
       }
       /* Update FIFO status */
       adcHandler.fifoTailX = tailX;
       adcHandler.fifoLengthX = lengthX;
       adcHandler.fifoTailY = tailY;
       adcHandler.fifoLengthY = lengthY;
       
       reg = reg & (~ADC_INT);
       writew(REG_ADC_CON, reg);
       if (adcHandler.adc_callback != NULL)
       {
          adcHandler.adc_callback(reg, adcHandler.adc_userData);
       }
       //reg = reg & (~ADC_INT);
       //writew(REG_ADC_CON, reg);
    } 
    
    if ((reg & ADC_WT_INT) == ADC_WT_INT)
    {
       reg = reg & (~ADC_WT_INT);
       writew(REG_ADC_CON, reg);
       
       if (adcHandler.wt_callback != NULL)
       {
          adcHandler.wt_callback(reg, adcHandler.wt_userData);
       } 
       //reg = reg & (~ADC_WT_INT);
       //writew(REG_ADC_CON, reg);
    }
    
    if ((reg & ADC_LV_INT) == ADC_LV_INT)
    {
       reg = reg & (~ADC_LV_INT);
       writew(REG_ADC_CON, reg);
       if (adcHandler.lv_callback != NULL)
       {
          adcHandler.lv_callback(reg, adcHandler.lv_userData);
       }
       //reg = reg & (~ADC_LV_INT);
       //writew(REG_ADC_CON, reg);
    }
    
    
    /* For safe */
    
    reg = readw(REG_ADC_CON);

    return CYG_ISR_HANDLED;
}
#else
VOID adcISR()
{
    UINT32 reg, temp;
    INT16 valueX, valueY;
    INT32 headX, tailX, lengthX;
    INT32 headY, tailY, lengthY;
    INT16 *fifoX, *fifoY;
    ADC_TSC_MODE mode;
    //INT32 i;

    headX   = adcHandler.fifoHeadX;
    tailX   = adcHandler.fifoTailX;
    lengthX = adcHandler.fifoLengthX;
    headY   = adcHandler.fifoHeadY;
    tailY   = adcHandler.fifoTailY;
    lengthY = adcHandler.fifoLengthY;    
    
    fifoX   = adcHandler.fifoX;
    fifoY   = adcHandler.fifoY;
    mode    = adcHandler.mode;
    
    reg = readw(REG_ADC_CON);
    
    
    if ((reg & ADC_INT) == ADC_INT)
    {
       if ( (lengthX<ADC_FIFO_LENGTH) && (lengthY<ADC_FIFO_LENGTH))
       {
          if (mode == NORMAL)
          {
             valueX = readw(REG_ADC_XDATA);
                    
             fifoX[tailX] = valueX;
             lengthX++;

    	     tailX++;
             if (tailX == ADC_FIFO_LENGTH)
             {
                tailX = 0;
             }  
          }
 
          if (mode == SEMIAUTO)
          {
             temp = readw(REG_ADC_TSC);
             
             if ((temp & ADC_TSC_XY) == 0)
             {
                valueX = readw(REG_ADC_XDATA);
                    
                fifoX[tailX] = valueX;
                lengthX++;

    	        tailX++;
                if (tailX == ADC_FIFO_LENGTH)
                {
                   tailX = 0;
                }             
             }
             else
             {
                valueY = readw(REG_ADC_YDATA);
                    
                fifoY[tailY] = valueY;
                lengthY++;
    	        tailY++;
                if (tailY == ADC_FIFO_LENGTH)
                {
                   tailY = 0;
                }             
             }    
          } 
          
          if (mode == AUTO)
          {
             valueX = readw(REG_ADC_XDATA);
             valueY = readw(REG_ADC_YDATA);       
             fifoX[tailX] = valueX;
             fifoY[tailY] = valueY;
             lengthX++;
             lengthY++;
    	     tailX++;
    	     tailY++;
             if (tailX == ADC_FIFO_LENGTH)
             {
                tailX = 0;
             }           
             if (tailY == ADC_FIFO_LENGTH)
             {
                tailY = 0;
             }            
          }
       }
       /* Update FIFO status */
       adcHandler.fifoTailX = tailX;
       adcHandler.fifoLengthX = lengthX;
       adcHandler.fifoTailY = tailY;
       adcHandler.fifoLengthY = lengthY;
       
       reg = reg & (~ADC_INT);
       writew(REG_ADC_CON, reg);
       if (adcHandler.adc_callback != NULL)
       {
          adcHandler.adc_callback(reg, adcHandler.adc_userData);
       }
       //reg = reg & (~ADC_INT);
       //writew(REG_ADC_CON, reg);
    } 
    
    if ((reg & ADC_WT_INT) == ADC_WT_INT)
    {
       reg = reg & (~ADC_WT_INT);
       writew(REG_ADC_CON, reg);
       
       if (adcHandler.wt_callback != NULL)
       {
          adcHandler.wt_callback(reg, adcHandler.wt_userData);
       } 
       //reg = reg & (~ADC_WT_INT);
       //writew(REG_ADC_CON, reg);
    }
    
    if ((reg & ADC_LV_INT) == ADC_LV_INT)
    {
       reg = reg & (~ADC_LV_INT);
       writew(REG_ADC_CON, reg);
       if (adcHandler.lv_callback != NULL)
       {
          adcHandler.lv_callback(reg, adcHandler.lv_userData);
       }
       //reg = reg & (~ADC_LV_INT);
       //writew(REG_ADC_CON, reg);
    }
    
    
    /* For safe */
    
    reg = readw(REG_ADC_CON);

    return; 
}
#endif

/****************************************************************************
* FUNCTION
*   adcChangeTscMode
*
* DESCRIPTION
*   The ChangeTscMode function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   mode            ADC touch screen conversion mode
*
* OUTPUTS
*   Successful
*   ADC_ERR_ARGS    Wrong argument for adcChangeTscMode function
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
INT adcChangeTscMode(ADC_TSC_MODE mode)
{
    UINT32 reg;
            
    if (mode < 0 || mode > 3)
    {
       return ADC_ERR_ARGS;
    }
    adcHandler.mode = mode;
    reg = inpw(REG_ADC_CON);
    
    reg = (reg & (~0x0000C000)) | (mode << 14);
    outpw(REG_ADC_CON, reg);  
    return Successful;
}

/****************************************************************************
* FUNCTION
*   adcChangeChannel
*
* DESCRIPTION
*   The ChangeChannel function of ADC device library
*
* CALLED BY
*   various components
*
* INPUTS
*   channel         Select ADC input for normal mode
*
* OUTPUTS
*   Successful
*   ADC_ERR_ARGS    Wrong argument for adcChangeTscMode function
*
* HISTORY
*   NAME        DATE        REMARKS
*   NM51 WTLiu  12/27/05    Created initial version 1.0
*
* REMARK
*     None
****************************************************************************/
INT adcChangeChannel(ADC_CHAN channel)
{
    UINT32 reg;
            
    if (channel < 0 || channel > 7)
    {
       return ADC_ERR_ARGS;
    }
    reg = inpw(REG_ADC_CON);
    
    reg = (reg & (~0x00000E00)) | (channel << 9);
    outpw(REG_ADC_CON, reg);  
    return Successful;
}